package edu.stanford.bmir.protege.web.server.stkosutil.statistics;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;

import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.RemoveAxiom;

import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.MatchLevel;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.MetaItemList;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.statistics.StatisticsResult;
import edu.stanford.bmir.protege.web.server.owlapi.OWLAPIProject;
import edu.stanford.bmir.protege.web.server.owlapi.OWLAPIProjectManager;
import edu.stanford.bmir.protege.web.server.owlapi.RenderingManager;
import edu.stanford.bmir.protege.web.server.stkosutil.mapper.OwlClassHolder;
import edu.stanford.bmir.protege.web.server.stkosutil.mapper.OwlClassHolderComparator;
import edu.stanford.bmir.protege.web.shared.project.ProjectId;
import edu.stanford.bmir.protege.web.shared.user.UserId;

public class EntityCounter {
	public StatisticsResult countEntities(String projectName){
		StatisticsResult result = new StatisticsResult();
		OWLAPIProject project = this.getProject(projectName);
		this.countClass(project, result);
		this.countDataProperty(project, result);
		this.countObjectProperty(project, result);
		this.countIndividual(project, result);
		return result;
	}
	
	private OWLAPIProject getProject(String projectName) {
		if (projectName == null) {
			throw new NullPointerException("projectName must not be null");
		}
		ProjectId projectId = ProjectId.get(projectName);
		// TODO: Log
		return getProject(projectId);
	}

	/**
	 * Gets the OWLAPIProject for a given {@link ProjectId}.If a project with
	 * the specified id exists then that project will be returned, otherwise, a
	 * fresh project will be created and that fresh project returned.
	 * 
	 * @param projectId
	 *            The id of the project.
	 * @return The OWL API project. Not <code>null</code>.
	 */
	private OWLAPIProject getProject(ProjectId projectId) {
		OWLAPIProjectManager pm = OWLAPIProjectManager.getProjectManager();
		return pm.getProject(projectId);
	}
	private void countClass(OWLAPIProject project, StatisticsResult result){
		  OWLDataFactory df = project.getDataFactory();
		  //RenderingManager rm = project.getRenderingManager();
		  Set<OWLClass> sClassList = project.getRootOntology().getClassesInSignature();
		
		  for (OWLClass owlClass: sClassList){
			  boolean isOriginal = true;
			  result.setTotalClassNumber(result.getTotalClassNumber() + 1);
			  for (OWLAnnotation annotation : owlClass.getAnnotations(project.getRootOntology(), df.getRDFSComment())) {
		    		 if (annotation.getValue() instanceof OWLLiteral) {
			    		 OWLLiteral commentValue = (OWLLiteral) annotation.getValue();
			    		 String value = commentValue.getLiteral();
			    		  if (MetaItemList.isCutFlag(value)){
			    			  result.setCutClassNumber(result.getCutClassNumber() + 1);
			    		  }else if (MetaItemList.isMergedFlag(value)){
			    			  isOriginal=false;
			    			  result.setMergedClassNumber(result.getMergedClassNumber()+1);
			    		  }else if (MetaItemList.isEnrichedFlag(value)){
			    			  isOriginal=false;
			    			  result.setEnrichedClassNumber(result.getEnrichedClassNumber()+1);
			    		  }
		    		 }//end if
	 		  }//end for 
			  if (isOriginal){
				  result.setOriginalClassNumber(result.getOriginalClassNumber()+1);
			  }
		  }

	  }
	
	private void countIndividual(OWLAPIProject project, StatisticsResult result){
		  OWLDataFactory df = project.getDataFactory();
		  //RenderingManager rm = project.getRenderingManager();
		  Set<OWLNamedIndividual> sO1Individuals = project.getRootOntology().getIndividualsInSignature();
	 	  for (OWLNamedIndividual o1NamedIndividual: sO1Individuals){
			  boolean isOriginal = true;
			  result.setTotalIndividualNumber(result.getTotalIndividualNumber() + 1);
			  for (OWLAnnotation annotation : o1NamedIndividual.getAnnotations(project.getRootOntology(), df.getRDFSComment())) {
		    		 if (annotation.getValue() instanceof OWLLiteral) {
			    		 OWLLiteral commentValue = (OWLLiteral) annotation.getValue();
			    		 String value = commentValue.getLiteral();
			    		  if (MetaItemList.isCutFlag(value)){
			    			  result.setCutIndividualNumber(result.getCutIndividualNumber() + 1);
			    		  }else if (MetaItemList.isMergedFlag(value)){
			    			  isOriginal=false;
			    			  result.setMergedIndividualNumber(result.getMergedIndividualNumber() + 1);
			    		  }else if (MetaItemList.isEnrichedFlag(value)){
			    			  isOriginal=false;
			    			 
			    		  }
		    		 }//end if
	 			}//end for  
			  if (isOriginal){
				  result.setOriginalIndividualNumber(result.getOriginalIndividualNumber()+1);
			  }
		  }

	  }
	
	private void countObjectProperty(OWLAPIProject project, StatisticsResult result){
		  OWLDataFactory df = project.getDataFactory();
		  //RenderingManager rm = project.getRenderingManager();
		  Set<OWLObjectProperty> sPropertyList = project.getRootOntology().getObjectPropertiesInSignature();
		  for (OWLObjectProperty property: sPropertyList){
			  boolean isOriginal = true;
			  result.setTotalPropertyNumber(result.getTotalPropertyNumber() + 1);
			  for (OWLAnnotation annotation : property.getAnnotations(project.getRootOntology(), df.getRDFSComment())) {
		    		 if (annotation.getValue() instanceof OWLLiteral) {
			    		 OWLLiteral commentValue = (OWLLiteral) annotation.getValue();
			    		 String value = commentValue.getLiteral();
			    		  if (MetaItemList.isCutFlag(value)){
			    			  result.setCutPropertyNumber(result.getCutPropertyNumber() + 1);
			    		  }else if (MetaItemList.isMergedFlag(value)){
			    			  isOriginal=false;
			    			  result.setMergedPropertyNumber(result.getMergedPropertyNumber() + 1);
			    		  }else if (MetaItemList.isEnrichedFlag(value)){
			    			  isOriginal=false;
			    			  result.setEnrichedPropertyNumber(result.getEnrichedPropertyNumber()+1);
			    		  }
		    		 }//end if
	 			}//end for  
			  if (isOriginal){
				  result.setOriginalPropertyNumber(result.getOriginalPropertyNumber()+1);
			  }
		  }

	  }
	
	private void countDataProperty(OWLAPIProject project, StatisticsResult result){
		  OWLDataFactory df = project.getDataFactory();
		  //RenderingManager rm = project.getRenderingManager();
		  Set<OWLDataProperty> sPropertyList = project.getRootOntology().getDataPropertiesInSignature();
		  for (OWLDataProperty property: sPropertyList){
			  boolean isOriginal = true;
			  result.setTotalPropertyNumber(result.getTotalPropertyNumber() + 1);
			  for (OWLAnnotation annotation : property.getAnnotations(project.getRootOntology(), df.getRDFSComment())) {
		    		 if (annotation.getValue() instanceof OWLLiteral) {
			    		 OWLLiteral commentValue = (OWLLiteral) annotation.getValue();
			    		 String value = commentValue.getLiteral();
			    		  if (MetaItemList.isCutFlag(value)){
			    			  result.setCutPropertyNumber(result.getCutPropertyNumber() + 1);
			    		  }else if (MetaItemList.isMergedFlag(value)){
			    			  isOriginal=false;
			    			  result.setMergedPropertyNumber(result.getMergedPropertyNumber() + 1);
			    		  }else if (MetaItemList.isEnrichedFlag(value)){
			    			  isOriginal=false;
			    			  result.setEnrichedPropertyNumber(result.getEnrichedPropertyNumber() + 1);
			    		  }
		    		 }//end if
	 			}//end for  
			  if (isOriginal){
				  result.setOriginalPropertyNumber(result.getOriginalPropertyNumber()+1);
			  }
		  }

	  }
}
